#ifndef LOG_H_
#define LOG_H_

#include <iostream>
#include <glibmm.h>
#include <boost/lexical_cast.hpp>

#include "strfuncs.h"
#include "options.h"
#include "url.h"

namespace gpyp {
namespace log {

extern Glib::StaticMutex _static_mutex;

class Logger {
public:
  typedef size_t id_type;

private:
  static id_type _id;

private:
  id_type            id_;
  const char         sig_;
  std::ostream      &out_;
  std::stringstream *buffer_;

protected:
  void prepare_buffer();

public:
  template<typename T>
  inline Logger &operator<<(const T &message) {
    _static_mutex.lock();
    prepare_buffer();
    *buffer_ << message;
    _static_mutex.unlock();
    return *this;
  }
  Logger &operator<<(Logger &(*)(Logger &));

private:
  /* do not implement */
  Logger operator=(const Logger &logger);

public:
  inline Logger operator()() const {
    return *this;
  }

  inline bool operator==(id_type id) const {
    return id_ == id;
  }

  Logger(char sig, std::ostream &out);
  Logger(const Logger &logger);
  ~Logger();
};

struct MessageQueueEntry {
  Logger::id_type    id;
  Glib::ustring     *msg;
  bool               sent;
  MessageQueueEntry *next;

  inline MessageQueueEntry(Logger::id_type id, Glib::ustring *msg) :
    id  (id),
    msg (msg),
    sent(false),
    next(NULL)
  {
  }
  inline ~MessageQueueEntry() {
    delete msg;
  }
};

template<>
Logger &Logger::operator<<(const Glib::ustring &message);
template<>
inline Logger &Logger::operator<<(const URL &url) {
  _static_mutex.lock();
  prepare_buffer();
  url.write(*buffer_, true);
  _static_mutex.unlock();
  return *this;
}

extern Logger log;
extern Logger err;
extern Logger dbg;

Logger &endl(Logger &l);

sigc::signal<void, Logger::id_type, const Glib::ustring &> signal_message();
MessageQueueEntry *get_messages();

void init(const OptionContext &opts);
void uninit();

}/*log*/
}/*gpyp*/

#endif/*LOG_H_*/
